package info.batcloud.fanli.core.service.impl;

import com.ctospace.archit.common.pagination.Paging;
import info.batcloud.fanli.core.constants.CacheNameConstants;
import info.batcloud.fanli.core.dto.BundleJsPackageDTO;
import info.batcloud.fanli.core.entity.BundleJsPackage;
import info.batcloud.fanli.core.enums.AppPlatform;
import info.batcloud.fanli.core.enums.BundleJsPackageStatus;
import info.batcloud.fanli.core.exception.BizException;
import info.batcloud.fanli.core.helper.PagingHelper;
import info.batcloud.fanli.core.repository.BundleJsPackageRepository;
import info.batcloud.fanli.core.service.BundleJsPackageService;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.inject.Inject;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Predicate;
import java.util.Date;
import java.util.List;

@Service
@CacheConfig(cacheNames = CacheNameConstants.BUNDLE_JS_PACKAGE)
public class BundleJsPackageServiceImpl implements BundleJsPackageService {

    @Inject
    private BundleJsPackageRepository bundleJsPackageRepository;


    @Override
    @Cacheable(key = "'BUNDLE_JS_' + #platform.name() + '_' + #appVersion")
    public BundleJsPackageDTO findLatestByPlatformAndAppVersion(AppPlatform platform, String appVersion) {
        BundleJsPackage bundleJsPackage = bundleJsPackageRepository.findTopByPlatformAndPlatformVersionAndStatusOrderByIdDesc(platform, appVersion, BundleJsPackageStatus.PUBLISHED);
        if(bundleJsPackage == null) {
            return null;
        }
        BundleJsPackageDTO dto = new BundleJsPackageDTO();
        BeanUtils.copyProperties(bundleJsPackage, dto);
        return dto;
    }

    @Override
    public BundleJsPackageDTO findLatestByPlatform(AppPlatform platform) {
        BundleJsPackage bundleJsPackage = bundleJsPackageRepository.findTopByPlatformAndStatusOrderByIdDesc(platform, BundleJsPackageStatus.PUBLISHED);
        if(bundleJsPackage == null) {
            return null;
        }
        BundleJsPackageDTO dto = new BundleJsPackageDTO();
        BeanUtils.copyProperties(bundleJsPackage, dto);
        return dto;
    }

    @Override
    @CacheEvict(key = "'BUNDLE_JS_' + #dto.getPlatform().name() + '_' + #dto.getPlatformVersion()")
    public void saveBundleJsPackage(BundleJsPackageAddDto dto) {
        if (this.bundleJsPackageRepository.countByPlatformAndPlatformVersionAndVersion(dto.getPlatform(),
                dto.getPlatformVersion(), dto.getVersion()) > 0) {
            throw new BizException("版本号已经存在，请更换版本号再进行保存！");
        }
        BundleJsPackage bundleJsPackage = new BundleJsPackage();
        bundleJsPackage.setPlatform(dto.getPlatform());
        bundleJsPackage.setPlatformVersion(dto.getPlatformVersion());
        bundleJsPackage.setVersion(dto.getVersion());
        bundleJsPackage.setCreateTime(new Date());
        bundleJsPackage.setStatus(BundleJsPackageStatus.WAIT_PUBLISH);
        bundleJsPackageRepository.save(bundleJsPackage);
    }

    @Override
    public Paging<BundleJsPackageDTO> search(SearchParam param) {
        Specification<BundleJsPackage> specification = (root, query, cb) -> {
            Predicate predicate = cb.conjunction();
            List<Expression<Boolean>> expressions = predicate.getExpressions();
            if (param.getPlatform() != null) {
                expressions.add(cb.greaterThanOrEqualTo(root.get("platform"), param.getPlatform()));
            }
            return predicate;
        };
        Sort sort = new Sort(Sort.Direction.DESC, "id");
        Pageable pageable = new PageRequest(param.getPage() - 1,
                param.getPageSize(), sort);
        Page<BundleJsPackage> page = bundleJsPackageRepository.findAll(specification, pageable);
        return PagingHelper.of(page, o -> {
            BundleJsPackageDTO dto = new BundleJsPackageDTO();
            BeanUtils.copyProperties(o, dto);
            return dto;
        }, param.getPage(), param.getPageSize());
    }

    @Override
    @CacheEvict(cacheNames = CacheNameConstants.BUNDLE_JS_PACKAGE, allEntries = true)
    public void publishBundleJsPackage(long id) {
        BundleJsPackage bundleJsPackage = bundleJsPackageRepository.findOne(id);
        bundleJsPackage.setStatus(BundleJsPackageStatus.PUBLISHED);
        bundleJsPackageRepository.save(bundleJsPackage);
    }

    @Override
    @CacheEvict(cacheNames = CacheNameConstants.BUNDLE_JS_PACKAGE, allEntries = true)
    public void deleteById(long id) {
        bundleJsPackageRepository.delete(id);
    }

    @Override
    @CacheEvict(cacheNames = CacheNameConstants.BUNDLE_JS_PACKAGE, allEntries = true)
    public void setUseCache(long id, boolean useCache) {
        BundleJsPackage bundleJsPackage = bundleJsPackageRepository.findOne(id);
        bundleJsPackage.setUseCache(useCache);
        bundleJsPackageRepository.save(bundleJsPackage);
    }

    @Override
    @CacheEvict(cacheNames = CacheNameConstants.BUNDLE_JS_PACKAGE, allEntries = true)
    public void setIosShow(long id, boolean iosShow) {
        BundleJsPackage bundleJsPackage = bundleJsPackageRepository.findOne(id);
        bundleJsPackage.setIosShow(iosShow);
        bundleJsPackageRepository.save(bundleJsPackage);
    }

    @Override
    @CacheEvict(cacheNames = CacheNameConstants.BUNDLE_JS_PACKAGE, allEntries = true)
    public void setShowUpdate(long id, boolean showUpdate) {
        BundleJsPackage bundleJsPackage = bundleJsPackageRepository.findOne(id);
        bundleJsPackage.setShowUpdate(showUpdate);
        bundleJsPackageRepository.save(bundleJsPackage);
    }

}
